/*
 * @copyright: Huang Ding
 * @Author: ding-cx
 * @Date: 2020-12-29 08:44:29
 * @LastEditors: ding-cx
 * @LastEditTime: 2021-10-30 12:17:54
 * @Description: file content
 */

import { Context, EggAppConfig, IResponseBodyData } from "egg";
import DineggError from "../../lib/core/DineggError";

/**
 *中间件，捕获业务中未捕获的错误，统一响应给前端数据，此中间件默认dinegg中不启用，可在业务中自己选择启用位置
 *
 * @param {*} options
 * @return {*}
 */
export default (options: EggAppConfig["catchNoCatchError"]) => {
	return async function catchError(ctx: Context, next: () => Promise<any>): Promise<void> {
		if (!options.enable) {
			return await next();
		}
		try {
			await next();
		} catch (error: any) {
			if (error instanceof Error && !(error instanceof DineggError)) {
				ctx.logger.error(`\r\n中间件捕获业务未处理异常!\r\n%s`, error);
			}
			if (!(error instanceof Object)) {
				return responseInnerError(ctx, error);
			}

			// 使用特殊标识标识业务错误，可以明文显示错误信息内容 ctx.throw 到此处
			if (error?.isDineggBizError || error instanceof DineggError) {
				responseBizError(ctx, error?.message || null);
			} else if (error?.isDineggBizSuccess) {
				// 使用特殊标识响应成功，可中断后续执行。 ctx.success ctx.error 都到此处
				responseBizSuccess(ctx, error?.sendData || null);
			} else {
				// 统一拦截业务未处理异常
				responseInnerError(ctx, error?.message || null);
			}
		}
	};
};

/** 响应内部系统异常 */
function responseInnerError(ctx: Context, msg: string) {
	const body: IResponseBodyData = {
		code: 50000,
		msg: `发生内部错误异常！`,
		data: null,
		details: [],
	};
	if (ctx.app.config.env !== "prod") {
		body.details = [msg];
	}
	ctx.body = body;
	ctx.status = 500;
}

/** 响应业务自定义抛出异常 */
function responseBizError(ctx: Context, msg: string) {
	const body: IResponseBodyData = {
		code: 50000,
		msg: msg || `发生未知业务异常！`,
		data: null,
		details: [],
	};
	ctx.body = body;
	ctx.status = 400;
}
/** 响应业务成功结果 */
function responseBizSuccess(ctx: Context, body: IResponseBodyData) {
	ctx.body = body;
	ctx.status = 200;
}
